package org.wzh.three.jvm.oom;

/**
 * 虚拟机栈和本地方法栈溢出
 * @author ewanhiz
 *
 * VM Args: -Xss128k
 *
 * 关于虚拟机展和本地方法栈,在 Java 虚拟机规范中描述了两种异常:
 * 如果新城请求的栈深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError 异常.
 * 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出 OutOfMemoryError 异常.
 *
 * 由于在 HotSpot 虚拟机中并不区分虚拟机栈和本地方法栈,因此,对于 HotSpot 来说,
 * 虽然 -Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由 -Xss 参数
 * 设定.
 */
public class JavaVMStackSOF {

    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    /**
     * 在实验中,将实验范围限制于单线程中的操作,尝试了下面两种方法均无法让虚拟机产生 OutOfMemoryError 异常.
     * 尝试的结果都是获得 StackOverflowError 异常.
     *  使用 -Xss 参数减少栈内存容量.结果: 抛出 StackOverflowError 异常,异常出现时输出栈深度相应缩小.
     *  定义了大量的本地变量,增大次方法帧中本地变量表的长度.结果: 抛出 StackOverflowError 异常时输出的堆栈深度相应缩小.
     * @param args
     */
    public static void main(String[] args) {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            e.printStackTrace();
        }
    }
    /**
     * 实验结果表明,在单个线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是 StackOverflowError 异常.
     *
     * 如果测试不限于单线程,通过不断地建立线程的方法倒是可以产生内存溢出异常.
     */

}
